#ifndef _COMMOM_IPC_H_
#define _COMMOM_IPC_H_

#include <sys/types.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/sem.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <time.h>
#include <cstring>
#include <cstdio>
#include <cstdlib>

#define SUCCESS 0
#define FAIL   -1

#define UNIX_OVER_UDP_SERVER 1
#define UNIX_OVER_UDP_CLIENT  0

#define MAX_MSG_SIZE     512
#define MAX_SHM_SIZE     512
#define MAX_SOCKET_SIZE  1024*2
#define MAX_SOCKET_EACH_SEND_SIZE  1024

//#define WRITE_ERR_LOG

#ifdef WRITE_ERR_LOG

extern FILE *pLog;

#define err_printf(format, ...) do\
{ \
    pLog = fopen("./event.log", "a+");\
    time_t t = time(NULL);\
	fprintf(pLog, "%s%s: %d: "format"", ctime(&t), __FILE__, __LINE__, ##__VA_ARGS__);\
	fclose(pLog);\
}while(0);

#else

#define err_printf(format, ...) printf("%s: %d: "format"", __FILE__, __LINE__, ##__VA_ARGS__)

#endif


class MallocMem
{
    char *pBuffer;
    int length;
public:
    MallocMem(int byte);
    char *c_str();
    int set_buffer(char *pdata);
    int get_buffer(char *pdata);
    int size();
    virtual ~MallocMem();
};

class MessageData
{
public:
    long int m_type;
    int cmd;
    int valid_size;
    char m_buffer[MAX_MSG_SIZE];
public:
    MessageData();
    int ImportBuffer(char *pdata);
    int ExportBuffer(char *pdata);
};

class Message
{
    MessageData msg;
    int msg_id;
public:
    Message(key_t key);
    int send_msg();
    int recv_msg(long int type);
    int set_message(MessageData *message);
    int get_message(MessageData *message);
    int delete_msg();
};

class ShareMemoryData
{
public:
    int valid_size;
    char buffer[MAX_SHM_SIZE];
public:
    ShareMemoryData();
};

class ShareMemory
{
    int shm_id;
    ShareMemoryData *shm;
public:
    ShareMemory(key_t key);
    int get_shm(ShareMemoryData *shmptr);
    int set_shm(ShareMemoryData *shmptr);
    int delete_shm();
};

class Semaphore
{
    int sem_set_id;
    union semun
    {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
    } sem;
public:
    Semaphore(key_t key, int num_sems);
    int InitSem(int index, int value);
    int WaitSem(int index);
    int SignalSem(int index);
    int DeleteSem(int index);
};

class SocketDataHead
{
public:
    int cmd;
    int valid_size;
public:
    SocketDataHead();
};

class SocketData
{
public:
    SocketDataHead data_head;
    char buffer[MAX_SOCKET_SIZE];
public:
    SocketData();
    int set_cmd(int cmd);
    int get_cmd();
    int set_valid_size(int valid_size);
    int get_valid_size();
    int ImportBuffer(char *pdata);
    int ExportBuffer(char *pdata);
};

class SocketSession
{
    int new_fd;
    int listen_fd;
    int sock_type;
    int sock_domain;
    int sock_port;
    char *sock_ip;
    int sock_backlog;
    char *sock_path;
    int sock_path_size;
    SocketData sockdata;
    struct sockaddr_in RemoteAddr;
    struct sockaddr_in LocalAddr;
    struct sockaddr_un server_addr;
    struct sockaddr_un client_addr;
    int CommomSessionInit(int domain, int type, int backlog);
    int CommomOverTCPSend(int sockfd);
    int CommomOverTCPRecv(int sockfd);
    int CommomOverUDPSend(struct sockaddr_in *sock_addr, char *ipaddr, int port);
    int CommomOverUDPRecv(struct sockaddr_in *sock_addr);
public:
    SocketSession(char *ipaddr, int port, int domain, int type, int backlog);
    SocketSession(int domain, int type, int backlog, char *path, int path_size);
    virtual ~SocketSession();
    int SetSocketData(SocketData *pdata);
    int GetSocketData(SocketData *pdata);
    int InitServerSocket();
    int SetNoBlock();
    int SocketAccept();
    int SocketConnect();
    int SocketSend();
    int SocketRecv();
    int SocketCloseClient();
    int SocketCloseListen();
    int SetSocketSendBufSize(int size);
    int SetSocketRecvBufSize(int size);
};

#endif